package servidor.bancoServidor;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLException;
import java.util.ArrayList;

import javax.mail.MessagingException;

import servidor.controle.ClienteControlador;
import servidor.controle.ContaControlador;
import servidor.controle.Criptografa;
import servidor.controle.ExtratoControlador;
import servidor.controle.GerenteControlador;
import servidor.modelo.Cliente;
import servidor.modelo.Conta;
import servidor.modelo.Extrato;
import servidor.modelo.Gerente;
import servidor.modelo.TipoConta;
import servidor.modelo.TipoEstilo;
import servidor.modelo.TipoPessoa;

public class BancoProtocolo {
	private BufferedReader in;
	private PrintWriter out;

	public BancoProtocolo(BufferedReader in, PrintWriter out) {
		this.in = in;
		this.out = out;
	}

	public Cliente logarCliente(String loginUsuario, String senhaUsuario)
			throws SQLException {
		return ClienteControlador.get(loginUsuario, senhaUsuario);
	}

	public Gerente logarGerente(String loginUsuario, String senhaUsuario)
			throws SQLException {
		return GerenteControlador.get(loginUsuario, senhaUsuario);
	}

	// ClienteControlador

	private void acaoClienteControladorCria() throws IOException, SQLException,
			MessagingException {
		// Pega do cliente os parametros para o método ClienteControlador.cria
		Gerente gerente = GerenteControlador.get(Integer
				.parseInt(in.readLine()));
		String nome = in.readLine();
		String login = in.readLine();
		String email = in.readLine();
		String senha = in.readLine();
		TipoPessoa tipoDePessoa = (in.readLine().equalsIgnoreCase("FISICA")) ? TipoPessoa.FISICA
				: TipoPessoa.JURIDICA;
		String cpfCnpj = in.readLine();
		// Executa o método
		ClienteControlador.cria(gerente, nome, login, email, senha,
				tipoDePessoa, cpfCnpj);
		MandaEmail mandaEmail = new MandaEmail();
		String[] destino = new String[1];
		destino[0] = email;

		String mensagem = "Bem Vindo ao Banco Carioca\n\nSeu login:" + login
				+ "\n\n\nAtenciosamente,\n     Banco Carioca.";
		mandaEmail.sendSSLMessage(destino, "Bem Vindo ao Banco Carioca",
				mensagem);
	}

	private void acaoClienteControladorGetAll() throws SQLException {
		ArrayList<Cliente> clientes = ClienteControlador.getAll();
		// retorna os dados de todos os clientes do banco de dados ao programa
		// cliente
		out.println(ClienteControlador.parseString(clientes));
	}

	private void acaoClienteControladorGet() throws IOException {
		String param = in.readLine();
		Cliente cliente;
		int id = 0;

		try {
			id = Integer.parseInt(param); // Tenta pegar o id do Cliente
		} catch (NumberFormatException numberException) {
			// Se não era um número, era para executar a função get, passando um
			// login e uma senha
			String senha = in.readLine();
			cliente = ClienteControlador.get(param, senha);
			out.println(ClienteControlador.parseString(cliente)); // retorna os
																	// dados da
																	// entidade
																	// cliente
																	// ao
																	// programa
																	// cliente
			return;
		}

		cliente = ClienteControlador.get(id); // Executa o método

		out.println(ClienteControlador.parseString(cliente)); // retorna os
																// dados da
																// entidade
																// cliente ao
																// programa
																// cliente
	}

	private void acaoClienteControladorAtualiza() throws IOException {
		// Pega do cliente os parametros para o método
		// ClienteControlador.atualiza
		int id = Integer.parseInt(in.readLine());
		Gerente gerente = GerenteControlador.get(Integer
				.parseInt(in.readLine()));
		String nome = in.readLine();
		String login = in.readLine();
		String email = in.readLine();
		String senha = in.readLine();
		TipoPessoa tipoDePessoa = (in.readLine().equalsIgnoreCase("FISICA")) ? TipoPessoa.FISICA
				: TipoPessoa.JURIDICA;
		String cpfCnpj = in.readLine();
		// Executa o método
		ClienteControlador.atualiza(id, gerente, nome, login, email, senha,
				tipoDePessoa, cpfCnpj);
	}

	private void acaoClienteControladorExists() throws IOException {
		String login = in.readLine();
		out.println(ClienteControlador.exists(login));
	}

	private void acaoClienteControladorDelete() throws IOException,
			SQLException {
		int id = Integer.parseInt(in.readLine());
		ClienteControlador.delete(id);
	}

	private void escolheAcaoClienteControlador() throws NumberFormatException,
			IOException, SQLException, MessagingException {
		String inputLine = in.readLine();

		if (inputLine.equalsIgnoreCase("cria")) {
			acaoClienteControladorCria();
		} else if (inputLine.equalsIgnoreCase("atualiza")) {
			acaoClienteControladorAtualiza();
		} else if (inputLine.equalsIgnoreCase("delete")) {
			acaoClienteControladorDelete();
		} else if (inputLine.equalsIgnoreCase("exists")) {
			acaoClienteControladorExists();
		} else if (inputLine.equalsIgnoreCase("get")) {
			acaoClienteControladorGet();
		} else if (inputLine.equalsIgnoreCase("getAll")) {
			acaoClienteControladorGetAll();
		}
	}

	// ContaControlador

	private void acaoContaControladorGetAll() throws SQLException, IOException {
		String param = in.readLine();
		ArrayList<Conta> contas;
		if (param == null) {
			contas = ContaControlador.getAll();
			// retorna os dados de todas as contas do banco de dados ao programa
			// cliente

		} else {
			contas = ContaControlador.getAll(param);

		}
		out.println(ContaControlador.parseString(contas));
	}

	private void acaoContaControladorGet() throws IOException {
		String param = in.readLine();
		Conta conta;
		int id = 0;

		try {
			id = Integer.parseInt(param);
		} catch (NumberFormatException numberException) {
			if (param.equalsIgnoreCase("corrente")) {
				int clienteId = Integer.parseInt(in.readLine());
				ArrayList<Conta> contas;
				contas = ContaControlador.getCorrente(clienteId);
				out.println(ContaControlador.parseString(contas));
				return;

			}

			else {
				int clienteId = Integer.parseInt(in.readLine());
				ArrayList<Conta> contas;
				contas = ContaControlador.getPoupanca(clienteId);
				out.println(ContaControlador.parseString(contas));
				return;
			}

		}

		conta = ContaControlador.get(id);
		out.println(ContaControlador.parseString(conta));
	}

	private void acaoContaControladorTransferir() throws IOException {
		// Pega do cliente os parametros para o método
		// ContaControlador.transferir
		int reais = Integer.parseInt(in.readLine());
		int centavos = Integer.parseInt(in.readLine());
		int contaOrigemId = Integer.parseInt(in.readLine());
		int contaDestinoId = Integer.parseInt(in.readLine());
		// Executa o método
		ContaControlador.transferir(reais, centavos, contaOrigemId,
				contaDestinoId);
	}

	private void acaoContaControladorSacar() throws IOException {
		// Pega do cliente os parametros para o método ContaControlador.sacar
		int reais = Integer.parseInt(in.readLine());
		int centavos = Integer.parseInt(in.readLine());
		int contaId = Integer.parseInt(in.readLine());
		// Executa o método
		ContaControlador.sacar(reais, centavos, contaId);
	}

	private void acaoContaControladorDepositar() throws IOException {
		// Pega do cliente os parametros para o método
		// ContaControlador.depositar
		int reais = Integer.parseInt(in.readLine());
		int centavos = Integer.parseInt(in.readLine());
		int contaId = Integer.parseInt(in.readLine());
		// Executa o método
		ContaControlador.depositar(reais, centavos, contaId);
	}

	private void acaoContaControladorAtualiza() throws IOException,
			SQLException {
		// Pega do cliente os parametros para o método ContaControlador.atualiza
		int id = Integer.parseInt(in.readLine());
		Cliente cliente = ClienteControlador.get(Integer
				.parseInt(in.readLine()));
		TipoConta tipoDeConta = (in.readLine().equalsIgnoreCase("CORRENTE")) ? TipoConta.CORRENTE
				: TipoConta.POUPANCA;
		TipoEstilo estiloDeConta = (in.readLine().equalsIgnoreCase("SIMPLES")) ? TipoEstilo.SIMPLES
				: TipoEstilo.ESPECIAL;
		// Executa o método
		ContaControlador.atualiza(id, cliente, tipoDeConta, estiloDeConta);
	}

	private void acaoContaControladorExists() throws NumberFormatException,
			IOException {
		int clienteId;
		try {
			clienteId = Integer.parseInt(in.readLine());
		} catch (NumberFormatException e) {
			// Se caiu aqui é porque ele passou a String "conta" em vez de um
			// id.
			// Indicando que é para executar contaExists.
			int id = Integer.parseInt(in.readLine());
			out.println(ContaControlador.contaExists(id));
			return;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			clienteId = 0;
			e.printStackTrace();
		}
		out.println(ContaControlador.exists(clienteId));

	}

	private void acaoContaControladorCria() throws IOException, SQLException {
		// Pega do cliente os parametros para o método ContaControlador.cria
		Cliente cliente = ClienteControlador.get(Integer
				.parseInt(in.readLine()));
		TipoConta tipoDeConta = (in.readLine().equalsIgnoreCase("CORRENTE")) ? TipoConta.CORRENTE
				: TipoConta.POUPANCA;
		int reais = Integer.parseInt(in.readLine());
		int centavos = Integer.parseInt(in.readLine());
		TipoEstilo estiloDeConta = (in.readLine().equalsIgnoreCase("SIMPLES")) ? TipoEstilo.SIMPLES
				: TipoEstilo.ESPECIAL;
		// Executa o método
		ContaControlador.cria(cliente, tipoDeConta, reais, centavos,
				estiloDeConta);
	}

	private void acaoContaControladorDelete() throws IOException, SQLException {
		int id = Integer.parseInt(in.readLine());
		ContaControlador.delete(id);
	}

	private void escolheAcaoContaControlador() throws IOException, SQLException {
		String inputLine = in.readLine();

		if (inputLine.equalsIgnoreCase("cria")) {
			acaoContaControladorCria();
		} else if (inputLine.equalsIgnoreCase("atualiza")) {
			acaoContaControladorAtualiza();
		} else if (inputLine.equalsIgnoreCase("delete")) {
			acaoContaControladorDelete();
		} else if (inputLine.equalsIgnoreCase("depositar")) {
			acaoContaControladorDepositar();
		} else if (inputLine.equalsIgnoreCase("sacar")) {
			acaoContaControladorSacar();
		} else if (inputLine.equalsIgnoreCase("transferir")) {
			acaoContaControladorTransferir();
		} else if (inputLine.equalsIgnoreCase("exists")) {
			acaoContaControladorExists();
		} else if (inputLine.equalsIgnoreCase("get")) {
			acaoContaControladorGet();
		} else if (inputLine.equalsIgnoreCase("getAll")) {
			acaoContaControladorGetAll();
		}
	}

	// GerenteControlador

	private void acaoGerenteControladorGetAll() throws SQLException {
		ArrayList<Gerente> gerentes = GerenteControlador.getAll();
		// retorna os dados de todos os clientes do banco de dados ao programa
		// cliente
		out.println(GerenteControlador.parseString(gerentes));
	}

	private void acaoGerenteControladorGet() throws IOException {
		String param = in.readLine();
		Gerente gerente;
		int id = 0;

		try {
			id = Integer.parseInt(param); // Tenta pegar o id do Cliente
		} catch (NumberFormatException numberException) {
			// Se não era um número, era para executar a função get, passando um
			// login e uma senha
			String senha = in.readLine();
			gerente = GerenteControlador.get(param, senha);

			out.println(GerenteControlador.parseString(gerente)); // retorna os
																	// dados da
																	// entidade
																	// cliente
																	// ao
																	// programa
																	// cliente
			return;
		}

		gerente = GerenteControlador.get(id); // Executa o método
		out.println(GerenteControlador.parseString(gerente)); // retorna os
																// dados da
																// entidade
																// cliente ao
																// programa
																// cliente
	}

	private void acaoGerenteControladorAtualiza() throws IOException {
		// Pega do cliente os parametros para o método
		// GerenteControlador.atualiza
		int id = Integer.parseInt(in.readLine());
		String nome = in.readLine();
		String login = in.readLine();
		String senha = in.readLine();
		// Executa o método
		GerenteControlador.atualiza(id, nome, login, senha);
	}

	private void acaoGerenteControladorCria() throws IOException, SQLException {
		// Pega do cliente os parametros para o método GerenteControlador.cria
		String nome = in.readLine();
		String login = in.readLine();
		String senha = in.readLine();
		// Executa o método
		GerenteControlador.cria(nome, login, senha);
	}

	private void acaoGerenteControladorExists() throws IOException {
		String login = in.readLine();
		out.println(GerenteControlador.exists(login));
	}

	private void acaoGerenteControladorDelete() throws IOException,
			SQLException {
		int id = Integer.parseInt(in.readLine());
		GerenteControlador.delete(id);
	}

	private void escolheAcaoGerenteControlador() throws NumberFormatException,
			IOException, SQLException {
		String inputLine = in.readLine();

		if (inputLine.equalsIgnoreCase("cria")) {
			acaoGerenteControladorCria();
		} else if (inputLine.equalsIgnoreCase("atualiza")) {
			acaoGerenteControladorAtualiza();
		} else if (inputLine.equalsIgnoreCase("delete")) {
			acaoGerenteControladorDelete();
		} else if (inputLine.equalsIgnoreCase("exists")) {
			acaoGerenteControladorExists();
		} else if (inputLine.equalsIgnoreCase("get")) {
			acaoGerenteControladorGet();
		} else if (inputLine.equalsIgnoreCase("getAll")) {
			acaoGerenteControladorGetAll();
		}
	}

	private void acaoExtratoControladorGetExtratoDaConta() throws IOException {
		int contaId = Integer.parseInt(in.readLine());
		ArrayList<Extrato> extratos = ExtratoControlador
				.getExtratoDaConta(contaId);
		out.println(ExtratoControlador.parseString(extratos));
	}

	private void escolheAcaoExtratoControlador() throws IOException {
		String inputLine = in.readLine();

		if (inputLine.equalsIgnoreCase("getExtratoDaConta")) {
			acaoExtratoControladorGetExtratoDaConta();
		}
	}

	private void acaoLogarCliente() throws IOException, SQLException {
		String inputLine = in.readLine();
		String[] logar = inputLine.split("-");
		String loginUsuario = logar[0];
		String senhaUsuario = logar[1];
		Cliente cliente = logarCliente(loginUsuario, senhaUsuario);
		if (cliente != null) {
			System.out.println("Cliente logado");
			out.println(Criptografa.md5("logado"));
			out.println(cliente.getID());
		} else {
			System.out.println("Falha ao logar o gerente");
			out.println(Criptografa.md5("precisa logar"));
		}
	}

	private void acaoLogarGerente() throws SQLException, IOException {
		String inputLine = in.readLine();
		String[] logar = inputLine.split("-");
		String loginUsuario = logar[0];
		String senhaUsuario = logar[1];
		Gerente gerente = logarGerente(loginUsuario, senhaUsuario);
		if (gerente != null) {
			System.out.println("Gerente logado");
			out.println(Criptografa.md5("logado"));
			out.println(gerente.getID());
		} else {
			System.out.println("Falha ao logar o gerente");
			out.println(Criptografa.md5("precisa logar"));
		}
	}

	// Se o cliente não pediu uma classe retorna false.
	// Se ele pediu uma ação de uma classe irá executá-la e retornará true.

	public void escolheAcao(String inputLine) throws NumberFormatException,
			IOException, SQLException, MessagingException {
		if (inputLine.equalsIgnoreCase("ClienteControlador")) {
			escolheAcaoClienteControlador();
		} else if (inputLine.equalsIgnoreCase("ContaControlador")) {
			escolheAcaoContaControlador();
		} else if (inputLine.equalsIgnoreCase("GerenteControlador")) {
			escolheAcaoGerenteControlador();
		} else if (inputLine.equalsIgnoreCase("ExtratoControlador")) {
			escolheAcaoExtratoControlador();
		} else if (inputLine.equalsIgnoreCase("logarCliente")) {
			acaoLogarCliente();
		} else if (inputLine.equalsIgnoreCase("logarGerente")) {
			acaoLogarGerente();
		}
	}
}
